/*
The LZMA impementation is taken from https://npm.is/lzma-js, converted to an ES module and with some features stripped off (e.g. async mode, worker support)

Here's the according MIT license:

© 2016 Nathan Rugg <nmrugg@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import * as base64 from './base64.mjs'

const __4294967296 = 4294967296,
  N1_longLit = [4294967295, -__4294967296],
  MIN_VALUE = [0, -9223372036854775808],
  P0_longLit = [0, 0],
  P1_longLit = [1, 0]

function add(a, b) {
  return create(a[0] + b[0], a[1] + b[1])
}

function initDim(len) {
  // NOTE: This is MUCH faster than "initDim(len)" in newer versions of v8 (starting with Node.js 0.11.15, which uses v8 3.28.73).
  var a = []
  a[len - 1] = undefined
  return a
}
function and(a, b) {
  return makeFromBits(
    ~~Math.max(Math.min(a[1] / __4294967296, 2147483647), -2147483648) &
      ~~Math.max(Math.min(b[1] / __4294967296, 2147483647), -2147483648),
    lowBits_0(a) & lowBits_0(b)
  )
}
function compare(a, b) {
  var nega, negb
  if (a[0] == b[0] && a[1] == b[1]) {
    return 0
  }
  nega = a[1] < 0
  negb = b[1] < 0
  if (nega && !negb) {
    return -1
  }
  if (!nega && negb) {
    return 1
  }
  if (sub(a, b)[1] < 0) {
    return -1
  }
  return 1
}

function create(valueLow, valueHigh) {
  var diffHigh, diffLow
  valueHigh %= 1.8446744073709552e19
  valueLow %= 1.8446744073709552e19
  diffHigh = valueHigh % __4294967296
  diffLow = Math.floor(valueLow / __4294967296) * __4294967296
  valueHigh = valueHigh - diffHigh + diffLow
  valueLow = valueLow - diffLow + diffHigh
  while (valueLow < 0) {
    valueLow += __4294967296
    valueHigh -= __4294967296
  }
  while (valueLow > 4294967295) {
    valueLow -= __4294967296
    valueHigh += __4294967296
  }
  valueHigh = valueHigh % 1.8446744073709552e19
  while (valueHigh > 9223372032559808512) {
    valueHigh -= 1.8446744073709552e19
  }
  while (valueHigh < -9223372036854775808) {
    valueHigh += 1.8446744073709552e19
  }
  return [valueLow, valueHigh]
}
function eq(a, b) {
  return a[0] == b[0] && a[1] == b[1]
}
function fromInt(value) {
  if (value >= 0) {
    return [value, 0]
  } else {
    return [value + __4294967296, -__4294967296]
  }
}

function lowBits_0(a) {
  if (a[0] >= 2147483648) {
    return ~~Math.max(Math.min(a[0] - __4294967296, 2147483647), -2147483648)
  } else {
    return ~~Math.max(Math.min(a[0], 2147483647), -2147483648)
  }
}
function makeFromBits(highBits, lowBits) {
  var high, low
  high = highBits * __4294967296
  low = lowBits
  if (lowBits < 0) {
    low += __4294967296
  }
  return [low, high]
}

function pwrAsDouble(n) {
  if (n <= 30) {
    return 1 << n
  } else {
    return pwrAsDouble(30) * pwrAsDouble(n - 30)
  }
}

function shl(a, n) {
  var diff, newHigh, newLow, twoToN
  n &= 63
  if (eq(a, MIN_VALUE)) {
    if (!n) {
      return a
    }
    return P0_longLit
  }
  if (a[1] < 0) {
    throw new Error('Neg')
  }
  twoToN = pwrAsDouble(n)
  newHigh = (a[1] * twoToN) % 1.8446744073709552e19
  newLow = a[0] * twoToN
  diff = newLow - (newLow % __4294967296)
  newHigh += diff
  newLow -= diff
  if (newHigh >= 9223372036854775807) {
    newHigh -= 1.8446744073709552e19
  }
  return [newLow, newHigh]
}

function shr(a, n) {
  var shiftFact
  n &= 63
  shiftFact = pwrAsDouble(n)
  return create(Math.floor(a[0] / shiftFact), a[1] / shiftFact)
}

function shru(a, n) {
  var sr
  n &= 63
  sr = shr(a, n)
  if (a[1] < 0) {
    sr = add(sr, shl([2, 0], 63 - n))
  }
  return sr
}
function sub(a, b) {
  return create(a[0] - b[0], a[1] - b[1])
}

function $ByteArrayInputStream(this$static, buf) {
  this$static.buf = buf
  this$static.pos = 0
  this$static.count = buf.length
  return this$static
}
function $read(this$static) {
  if (this$static.pos >= this$static.count) return -1
  return this$static.buf[this$static.pos++] & 255
}
function $read_0(this$static, buf, off, len) {
  if (this$static.pos >= this$static.count) return -1
  len = Math.min(len, this$static.count - this$static.pos)
  arraycopy(this$static.buf, this$static.pos, buf, off, len)
  this$static.pos += len
  return len
}
function $ByteArrayOutputStream(this$static) {
  this$static.buf = initDim(32)
  this$static.count = 0
  return this$static
}

function $toByteArray(this$static) {
  var data = this$static.buf
  data.length = this$static.count
  return data
}
function $write(this$static, b) {
  this$static.buf[this$static.count++] = (b << 24) >> 24
}
function $write_0(this$static, buf, off, len) {
  arraycopy(buf, off, this$static.buf, this$static.count, len)
  this$static.count += len
}
function $getChars(this$static, srcBegin, srcEnd, dst, dstBegin) {
  var srcIdx
  for (srcIdx = srcBegin; srcIdx < srcEnd; ++srcIdx) {
    dst[dstBegin++] = this$static.charCodeAt(srcIdx)
  }
}
function arraycopy(src, srcOfs, dest, destOfs, len) {
  for (var i = 0; i < len; ++i) {
    dest[destOfs + i] = src[srcOfs + i]
  }
}
function $configure(this$static, encoder) {
  $SetDictionarySize_0(encoder, 1 << this$static.s)
  encoder._numFastBytes = this$static.f
  $SetMatchFinder(encoder, this$static.m)

  // lc is always 3
  // lp is always 0
  // pb is always 2
  encoder._numLiteralPosStateBits = 0
  encoder._numLiteralContextBits = 3
  encoder._posStateBits = 2
  encoder._posStateMask = 3
}

function $init(this$static, input, output, length_0, mode, enableEndMark) {
  var encoder, i
  if (compare(length_0, N1_longLit) < 0)
    throw new Error('invalid length ' + length_0)
  this$static.length_0 = length_0
  encoder = $Encoder({})
  $configure(mode, encoder)
  encoder._writeEndMark = enableEndMark
  $WriteCoderProperties(encoder, output)
  for (i = 0; i < 64; i += 8) $write(output, lowBits_0(shr(length_0, i)) & 255)
  this$static.chunker =
    ((encoder._needReleaseMFStream = 0),
    ((encoder._inStream = input),
    (encoder._finished = 0),
    $Create_2(encoder),
    (encoder._rangeEncoder.Stream = output),
    $Init_4(encoder),
    $FillDistancesPrices(encoder),
    $FillAlignPrices(encoder),
    (encoder._lenEncoder._tableSize = encoder._numFastBytes + 1 - 2),
    $UpdateTables(encoder._lenEncoder, 1 << encoder._posStateBits),
    (encoder._repMatchLenEncoder._tableSize = encoder._numFastBytes + 1 - 2),
    $UpdateTables(encoder._repMatchLenEncoder, 1 << encoder._posStateBits),
    (encoder.nowPos64 = P0_longLit),
    undefined),
    $Chunker_0({}, encoder))
}

function $LZMAByteArrayCompressor(this$static, data, mode, enableEndMark) {
  this$static.output = $ByteArrayOutputStream({})
  $init(
    this$static,
    $ByteArrayInputStream({}, data),
    this$static.output,
    fromInt(data.length),
    mode,
    enableEndMark
  )
  return this$static
}
function $init_0(this$static, input, output) {
  var decoder,
    hex_length = '',
    i,
    properties = [],
    r,
    tmp_length

  for (i = 0; i < 5; ++i) {
    r = $read(input)
    if (r == -1) throw new Error('truncated input')
    properties[i] = (r << 24) >> 24
  }

  decoder = $Decoder({})
  if (!$SetDecoderProperties(decoder, properties)) {
    throw new Error('corrupted input')
  }
  for (i = 0; i < 64; i += 8) {
    r = $read(input)
    if (r == -1) throw new Error('truncated input')
    r = r.toString(16)
    if (r.length == 1) r = '0' + r
    hex_length = r + '' + hex_length
  }

  // Was the length set in the header (if it was compressed from a stream, the length is all f"s).
  if (/^0+$|^f+$/i.test(hex_length)) {
    // The length is unknown, so set to -1.
    this$static.length_0 = N1_longLit
  } else {
    // NOTE: If there is a problem with the decoder because of the length, you can always set the length to -1 (N1_longLit) which means unknown.
    tmp_length = parseInt(hex_length, 16)
    // If the length is too long to handle, just set it to unknown.
    if (tmp_length > 4294967295) {
      this$static.length_0 = N1_longLit
    } else {
      this$static.length_0 = fromInt(tmp_length)
    }
  }

  this$static.chunker = $CodeInChunks(
    decoder,
    input,
    output,
    this$static.length_0
  )
}

function $LZMAByteArrayDecompressor(this$static, data) {
  this$static.output = $ByteArrayOutputStream({})
  $init_0(this$static, $ByteArrayInputStream({}, data), this$static.output)
  return this$static
}
function $Create_4(this$static, keepSizeBefore, keepSizeAfter, keepSizeReserv) {
  var blockSize
  this$static._keepSizeBefore = keepSizeBefore
  this$static._keepSizeAfter = keepSizeAfter
  blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv
  if (this$static._bufferBase == null || this$static._blockSize != blockSize) {
    this$static._bufferBase = null
    this$static._blockSize = blockSize
    this$static._bufferBase = initDim(this$static._blockSize)
  }
  this$static._pointerToLastSafePosition =
    this$static._blockSize - keepSizeAfter
}

function $GetIndexByte(this$static, index) {
  return this$static._bufferBase[
    this$static._bufferOffset + this$static._pos + index
  ]
}

function $GetMatchLen(this$static, index, distance, limit) {
  var i, pby
  if (this$static._streamEndWasReached) {
    if (this$static._pos + index + limit > this$static._streamPos) {
      limit = this$static._streamPos - (this$static._pos + index)
    }
  }
  ++distance
  pby = this$static._bufferOffset + this$static._pos + index
  for (
    i = 0;
    i < limit &&
    this$static._bufferBase[pby + i] ==
      this$static._bufferBase[pby + i - distance];
    ++i
  ) {}
  return i
}

function $GetNumAvailableBytes(this$static) {
  return this$static._streamPos - this$static._pos
}

function $MoveBlock(this$static) {
  var i, numBytes, offset
  offset =
    this$static._bufferOffset + this$static._pos - this$static._keepSizeBefore
  if (offset > 0) {
    --offset
  }
  numBytes = this$static._bufferOffset + this$static._streamPos - offset
  for (i = 0; i < numBytes; ++i) {
    this$static._bufferBase[i] = this$static._bufferBase[offset + i]
  }
  this$static._bufferOffset -= offset
}

function $MovePos_1(this$static) {
  var pointerToPostion
  ++this$static._pos
  if (this$static._pos > this$static._posLimit) {
    pointerToPostion = this$static._bufferOffset + this$static._pos
    if (pointerToPostion > this$static._pointerToLastSafePosition) {
      $MoveBlock(this$static)
    }
    $ReadBlock(this$static)
  }
}

function $ReadBlock(this$static) {
  var numReadBytes, pointerToPostion, size
  if (this$static._streamEndWasReached) return
  while (1) {
    size =
      -this$static._bufferOffset +
      this$static._blockSize -
      this$static._streamPos
    if (!size) return
    numReadBytes = $read_0(
      this$static._stream,
      this$static._bufferBase,
      this$static._bufferOffset + this$static._streamPos,
      size
    )
    if (numReadBytes == -1) {
      this$static._posLimit = this$static._streamPos
      pointerToPostion = this$static._bufferOffset + this$static._posLimit
      if (pointerToPostion > this$static._pointerToLastSafePosition) {
        this$static._posLimit =
          this$static._pointerToLastSafePosition - this$static._bufferOffset
      }
      this$static._streamEndWasReached = 1
      return
    }
    this$static._streamPos += numReadBytes
    if (
      this$static._streamPos >=
      this$static._pos + this$static._keepSizeAfter
    ) {
      this$static._posLimit =
        this$static._streamPos - this$static._keepSizeAfter
    }
  }
}

function $ReduceOffsets(this$static, subValue) {
  this$static._bufferOffset += subValue
  this$static._posLimit -= subValue
  this$static._pos -= subValue
  this$static._streamPos -= subValue
}

var CrcTable = (function() {
  var i,
    j,
    r,
    CrcTable = []
  for (i = 0; i < 256; ++i) {
    r = i
    for (j = 0; j < 8; ++j)
      if ((r & 1) != 0) {
        r = (r >>> 1) ^ -306674912
      } else {
        r >>>= 1
      }
    CrcTable[i] = r
  }
  return CrcTable
})()

function $Create_3(
  this$static,
  historySize,
  keepAddBufferBefore,
  matchMaxLen,
  keepAddBufferAfter
) {
  var cyclicBufferSize, hs, windowReservSize
  if (historySize < 1073741567) {
    this$static._cutValue = 16 + (matchMaxLen >> 1)
    windowReservSize =
      ~~(
        (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) /
        2
      ) + 256
    $Create_4(
      this$static,
      historySize + keepAddBufferBefore,
      matchMaxLen + keepAddBufferAfter,
      windowReservSize
    )
    this$static._matchMaxLen = matchMaxLen
    cyclicBufferSize = historySize + 1
    if (this$static._cyclicBufferSize != cyclicBufferSize) {
      this$static._son = initDim(
        (this$static._cyclicBufferSize = cyclicBufferSize) * 2
      )
    }

    hs = 65536
    if (this$static.HASH_ARRAY) {
      hs = historySize - 1
      hs |= hs >> 1
      hs |= hs >> 2
      hs |= hs >> 4
      hs |= hs >> 8
      hs >>= 1
      hs |= 65535
      if (hs > 16777216) hs >>= 1
      this$static._hashMask = hs
      ++hs
      hs += this$static.kFixHashSize
    }

    if (hs != this$static._hashSizeSum) {
      this$static._hash = initDim((this$static._hashSizeSum = hs))
    }
  }
}

function $GetMatches(this$static, distances) {
  var count,
    cur,
    curMatch,
    curMatch2,
    curMatch3,
    cyclicPos,
    delta,
    hash2Value,
    hash3Value,
    hashValue,
    len,
    len0,
    len1,
    lenLimit,
    matchMinPos,
    maxLen,
    offset,
    pby1,
    ptr0,
    ptr1,
    temp
  if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) {
    lenLimit = this$static._matchMaxLen
  } else {
    lenLimit = this$static._streamPos - this$static._pos
    if (lenLimit < this$static.kMinMatchCheck) {
      $MovePos_0(this$static)
      return 0
    }
  }
  offset = 0
  matchMinPos =
    this$static._pos > this$static._cyclicBufferSize
      ? this$static._pos - this$static._cyclicBufferSize
      : 0
  cur = this$static._bufferOffset + this$static._pos
  maxLen = 1
  hash2Value = 0
  hash3Value = 0
  if (this$static.HASH_ARRAY) {
    temp =
      CrcTable[this$static._bufferBase[cur] & 255] ^
      (this$static._bufferBase[cur + 1] & 255)
    hash2Value = temp & 1023
    temp ^= (this$static._bufferBase[cur + 2] & 255) << 8
    hash3Value = temp & 65535
    hashValue =
      (temp ^ (CrcTable[this$static._bufferBase[cur + 3] & 255] << 5)) &
      this$static._hashMask
  } else {
    hashValue =
      (this$static._bufferBase[cur] & 255) ^
      ((this$static._bufferBase[cur + 1] & 255) << 8)
  }

  curMatch = this$static._hash[this$static.kFixHashSize + hashValue] || 0
  if (this$static.HASH_ARRAY) {
    curMatch2 = this$static._hash[hash2Value] || 0
    curMatch3 = this$static._hash[1024 + hash3Value] || 0
    this$static._hash[hash2Value] = this$static._pos
    this$static._hash[1024 + hash3Value] = this$static._pos
    if (curMatch2 > matchMinPos) {
      if (
        this$static._bufferBase[this$static._bufferOffset + curMatch2] ==
        this$static._bufferBase[cur]
      ) {
        distances[offset++] = maxLen = 2
        distances[offset++] = this$static._pos - curMatch2 - 1
      }
    }
    if (curMatch3 > matchMinPos) {
      if (
        this$static._bufferBase[this$static._bufferOffset + curMatch3] ==
        this$static._bufferBase[cur]
      ) {
        if (curMatch3 == curMatch2) {
          offset -= 2
        }
        distances[offset++] = maxLen = 3
        distances[offset++] = this$static._pos - curMatch3 - 1
        curMatch2 = curMatch3
      }
    }
    if (offset != 0 && curMatch2 == curMatch) {
      offset -= 2
      maxLen = 1
    }
  }
  this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos
  ptr0 = (this$static._cyclicBufferPos << 1) + 1
  ptr1 = this$static._cyclicBufferPos << 1
  len0 = len1 = this$static.kNumHashDirectBytes
  if (this$static.kNumHashDirectBytes != 0) {
    if (curMatch > matchMinPos) {
      if (
        this$static._bufferBase[
          this$static._bufferOffset + curMatch + this$static.kNumHashDirectBytes
        ] != this$static._bufferBase[cur + this$static.kNumHashDirectBytes]
      ) {
        distances[offset++] = maxLen = this$static.kNumHashDirectBytes
        distances[offset++] = this$static._pos - curMatch - 1
      }
    }
  }
  count = this$static._cutValue
  while (1) {
    if (curMatch <= matchMinPos || count-- == 0) {
      this$static._son[ptr0] = this$static._son[ptr1] = 0
      break
    }
    delta = this$static._pos - curMatch
    cyclicPos =
      (delta <= this$static._cyclicBufferPos
        ? this$static._cyclicBufferPos - delta
        : this$static._cyclicBufferPos -
          delta +
          this$static._cyclicBufferSize) << 1
    pby1 = this$static._bufferOffset + curMatch
    len = len0 < len1 ? len0 : len1
    if (
      this$static._bufferBase[pby1 + len] == this$static._bufferBase[cur + len]
    ) {
      while (++len != lenLimit) {
        if (
          this$static._bufferBase[pby1 + len] !=
          this$static._bufferBase[cur + len]
        ) {
          break
        }
      }
      if (maxLen < len) {
        distances[offset++] = maxLen = len
        distances[offset++] = delta - 1
        if (len == lenLimit) {
          this$static._son[ptr1] = this$static._son[cyclicPos]
          this$static._son[ptr0] = this$static._son[cyclicPos + 1]
          break
        }
      }
    }
    if (
      (this$static._bufferBase[pby1 + len] & 255) <
      (this$static._bufferBase[cur + len] & 255)
    ) {
      this$static._son[ptr1] = curMatch
      ptr1 = cyclicPos + 1
      curMatch = this$static._son[ptr1]
      len1 = len
    } else {
      this$static._son[ptr0] = curMatch
      ptr0 = cyclicPos
      curMatch = this$static._son[ptr0]
      len0 = len
    }
  }
  $MovePos_0(this$static)
  return offset
}

function $Init_5(this$static) {
  this$static._bufferOffset = 0
  this$static._pos = 0
  this$static._streamPos = 0
  this$static._streamEndWasReached = 0
  $ReadBlock(this$static)
  this$static._cyclicBufferPos = 0
  $ReduceOffsets(this$static, -1)
}

function $MovePos_0(this$static) {
  var subValue
  if (++this$static._cyclicBufferPos >= this$static._cyclicBufferSize) {
    this$static._cyclicBufferPos = 0
  }
  $MovePos_1(this$static)
  if (this$static._pos == 1073741823) {
    subValue = this$static._pos - this$static._cyclicBufferSize
    $NormalizeLinks(
      this$static._son,
      this$static._cyclicBufferSize * 2,
      subValue
    )
    $NormalizeLinks(this$static._hash, this$static._hashSizeSum, subValue)
    $ReduceOffsets(this$static, subValue)
  }
}

// NOTE: This is only called after reading one whole gigabyte.
function $NormalizeLinks(items, numItems, subValue) {
  var i, value
  for (i = 0; i < numItems; ++i) {
    value = items[i] || 0
    if (value <= subValue) {
      value = 0
    } else {
      value -= subValue
    }
    items[i] = value
  }
}

function $SetType(this$static, numHashBytes) {
  this$static.HASH_ARRAY = numHashBytes > 2
  if (this$static.HASH_ARRAY) {
    this$static.kNumHashDirectBytes = 0
    this$static.kMinMatchCheck = 4
    this$static.kFixHashSize = 66560
  } else {
    this$static.kNumHashDirectBytes = 2
    this$static.kMinMatchCheck = 3
    this$static.kFixHashSize = 0
  }
}

function $Skip(this$static, num) {
  var count,
    cur,
    curMatch,
    cyclicPos,
    delta,
    hash2Value,
    hash3Value,
    hashValue,
    len,
    len0,
    len1,
    lenLimit,
    matchMinPos,
    pby1,
    ptr0,
    ptr1,
    temp
  do {
    if (this$static._pos + this$static._matchMaxLen <= this$static._streamPos) {
      lenLimit = this$static._matchMaxLen
    } else {
      lenLimit = this$static._streamPos - this$static._pos
      if (lenLimit < this$static.kMinMatchCheck) {
        $MovePos_0(this$static)
        continue
      }
    }
    matchMinPos =
      this$static._pos > this$static._cyclicBufferSize
        ? this$static._pos - this$static._cyclicBufferSize
        : 0
    cur = this$static._bufferOffset + this$static._pos
    if (this$static.HASH_ARRAY) {
      temp =
        CrcTable[this$static._bufferBase[cur] & 255] ^
        (this$static._bufferBase[cur + 1] & 255)
      hash2Value = temp & 1023
      this$static._hash[hash2Value] = this$static._pos
      temp ^= (this$static._bufferBase[cur + 2] & 255) << 8
      hash3Value = temp & 65535
      this$static._hash[1024 + hash3Value] = this$static._pos
      hashValue =
        (temp ^ (CrcTable[this$static._bufferBase[cur + 3] & 255] << 5)) &
        this$static._hashMask
    } else {
      hashValue =
        (this$static._bufferBase[cur] & 255) ^
        ((this$static._bufferBase[cur + 1] & 255) << 8)
    }
    curMatch = this$static._hash[this$static.kFixHashSize + hashValue]
    this$static._hash[this$static.kFixHashSize + hashValue] = this$static._pos
    ptr0 = (this$static._cyclicBufferPos << 1) + 1
    ptr1 = this$static._cyclicBufferPos << 1
    len0 = len1 = this$static.kNumHashDirectBytes
    count = this$static._cutValue
    while (1) {
      if (curMatch <= matchMinPos || count-- == 0) {
        this$static._son[ptr0] = this$static._son[ptr1] = 0
        break
      }
      delta = this$static._pos - curMatch
      cyclicPos =
        (delta <= this$static._cyclicBufferPos
          ? this$static._cyclicBufferPos - delta
          : this$static._cyclicBufferPos -
            delta +
            this$static._cyclicBufferSize) << 1
      pby1 = this$static._bufferOffset + curMatch
      len = len0 < len1 ? len0 : len1
      if (
        this$static._bufferBase[pby1 + len] ==
        this$static._bufferBase[cur + len]
      ) {
        while (++len != lenLimit) {
          if (
            this$static._bufferBase[pby1 + len] !=
            this$static._bufferBase[cur + len]
          ) {
            break
          }
        }
        if (len == lenLimit) {
          this$static._son[ptr1] = this$static._son[cyclicPos]
          this$static._son[ptr0] = this$static._son[cyclicPos + 1]
          break
        }
      }
      if (
        (this$static._bufferBase[pby1 + len] & 255) <
        (this$static._bufferBase[cur + len] & 255)
      ) {
        this$static._son[ptr1] = curMatch
        ptr1 = cyclicPos + 1
        curMatch = this$static._son[ptr1]
        len1 = len
      } else {
        this$static._son[ptr0] = curMatch
        ptr0 = cyclicPos
        curMatch = this$static._son[ptr0]
        len0 = len
      }
    }
    $MovePos_0(this$static)
  } while (--num != 0)
}
function $CopyBlock(this$static, distance, len) {
  var pos = this$static._pos - distance - 1
  if (pos < 0) {
    pos += this$static._windowSize
  }
  for (; len != 0; --len) {
    if (pos >= this$static._windowSize) {
      pos = 0
    }
    this$static._buffer[this$static._pos++] = this$static._buffer[pos++]
    if (this$static._pos >= this$static._windowSize) {
      $Flush_0(this$static)
    }
  }
}

function $Create_5(this$static, windowSize) {
  if (this$static._buffer == null || this$static._windowSize != windowSize) {
    this$static._buffer = initDim(windowSize)
  }
  this$static._windowSize = windowSize
  this$static._pos = 0
  this$static._streamPos = 0
}

function $Flush_0(this$static) {
  var size = this$static._pos - this$static._streamPos
  if (!size) {
    return
  }
  $write_0(
    this$static._stream,
    this$static._buffer,
    this$static._streamPos,
    size
  )
  if (this$static._pos >= this$static._windowSize) {
    this$static._pos = 0
  }
  this$static._streamPos = this$static._pos
}

function $GetByte(this$static, distance) {
  var pos = this$static._pos - distance - 1
  if (pos < 0) {
    pos += this$static._windowSize
  }
  return this$static._buffer[pos]
}

function $PutByte(this$static, b) {
  this$static._buffer[this$static._pos++] = b
  if (this$static._pos >= this$static._windowSize) {
    $Flush_0(this$static)
  }
}

function $ReleaseStream(this$static) {
  $Flush_0(this$static)
  this$static._stream = null
}
function GetLenToPosState(len) {
  len -= 2
  if (len < 4) {
    return len
  }
  return 3
}

function StateUpdateChar(index) {
  if (index < 4) {
    return 0
  }
  if (index < 10) {
    return index - 3
  }
  return index - 6
}
function $Chunker_0(this$static, encoder) {
  this$static.encoder = encoder
  this$static.decoder = null
  this$static.alive = 1
  return this$static
}
function $Chunker(this$static, decoder) {
  this$static.decoder = decoder
  this$static.encoder = null
  this$static.alive = 1
  return this$static
}
function $processChunk(this$static) {
  if (!this$static.alive) {
    throw new Error('bad state')
  }

  if (this$static.encoder) {
    $processEncoderChunk(this$static)
  } else {
    $processDecoderChunk(this$static)
  }

  return this$static.alive
}
function $processDecoderChunk(this$static) {
  var result = $CodeOneChunk(this$static.decoder)
  if (result == -1) {
    throw new Error('corrupted input')
  }
  this$static.inBytesProcessed = N1_longLit
  this$static.outBytesProcessed = this$static.decoder.nowPos64
  if (
    result ||
    (compare(this$static.decoder.outSize, P0_longLit) >= 0 &&
      compare(this$static.decoder.nowPos64, this$static.decoder.outSize) >= 0)
  ) {
    $Flush_0(this$static.decoder.m_OutWindow)
    $ReleaseStream(this$static.decoder.m_OutWindow)
    this$static.decoder.m_RangeDecoder.Stream = null
    this$static.alive = 0
  }
}
function $processEncoderChunk(this$static) {
  $CodeOneBlock(
    this$static.encoder,
    this$static.encoder.processedInSize,
    this$static.encoder.processedOutSize,
    this$static.encoder.finished
  )
  this$static.inBytesProcessed = this$static.encoder.processedInSize[0]
  if (this$static.encoder.finished[0]) {
    $ReleaseStreams(this$static.encoder)
    this$static.alive = 0
  }
}
function $CodeInChunks(this$static, inStream, outStream, outSize) {
  this$static.m_RangeDecoder.Stream = inStream
  $ReleaseStream(this$static.m_OutWindow)
  this$static.m_OutWindow._stream = outStream
  $Init_1(this$static)
  this$static.state = 0
  this$static.rep0 = 0
  this$static.rep1 = 0
  this$static.rep2 = 0
  this$static.rep3 = 0
  this$static.outSize = outSize
  this$static.nowPos64 = P0_longLit
  this$static.prevByte = 0
  return $Chunker({}, this$static)
}

function $CodeOneChunk(this$static) {
  var decoder2, distance, len, numDirectBits, posSlot, posState
  posState = lowBits_0(this$static.nowPos64) & this$static.m_PosStateMask
  if (
    !$DecodeBit(
      this$static.m_RangeDecoder,
      this$static.m_IsMatchDecoders,
      (this$static.state << 4) + posState
    )
  ) {
    decoder2 = $GetDecoder(
      this$static.m_LiteralDecoder,
      lowBits_0(this$static.nowPos64),
      this$static.prevByte
    )
    if (this$static.state < 7) {
      this$static.prevByte = $DecodeNormal(decoder2, this$static.m_RangeDecoder)
    } else {
      this$static.prevByte = $DecodeWithMatchByte(
        decoder2,
        this$static.m_RangeDecoder,
        $GetByte(this$static.m_OutWindow, this$static.rep0)
      )
    }
    $PutByte(this$static.m_OutWindow, this$static.prevByte)
    this$static.state = StateUpdateChar(this$static.state)
    this$static.nowPos64 = add(this$static.nowPos64, P1_longLit)
  } else {
    if (
      $DecodeBit(
        this$static.m_RangeDecoder,
        this$static.m_IsRepDecoders,
        this$static.state
      )
    ) {
      len = 0
      if (
        !$DecodeBit(
          this$static.m_RangeDecoder,
          this$static.m_IsRepG0Decoders,
          this$static.state
        )
      ) {
        if (
          !$DecodeBit(
            this$static.m_RangeDecoder,
            this$static.m_IsRep0LongDecoders,
            (this$static.state << 4) + posState
          )
        ) {
          this$static.state = this$static.state < 7 ? 9 : 11
          len = 1
        }
      } else {
        if (
          !$DecodeBit(
            this$static.m_RangeDecoder,
            this$static.m_IsRepG1Decoders,
            this$static.state
          )
        ) {
          distance = this$static.rep1
        } else {
          if (
            !$DecodeBit(
              this$static.m_RangeDecoder,
              this$static.m_IsRepG2Decoders,
              this$static.state
            )
          ) {
            distance = this$static.rep2
          } else {
            distance = this$static.rep3
            this$static.rep3 = this$static.rep2
          }
          this$static.rep2 = this$static.rep1
        }
        this$static.rep1 = this$static.rep0
        this$static.rep0 = distance
      }
      if (!len) {
        len =
          $Decode(
            this$static.m_RepLenDecoder,
            this$static.m_RangeDecoder,
            posState
          ) + 2
        this$static.state = this$static.state < 7 ? 8 : 11
      }
    } else {
      this$static.rep3 = this$static.rep2
      this$static.rep2 = this$static.rep1
      this$static.rep1 = this$static.rep0
      len =
        2 +
        $Decode(this$static.m_LenDecoder, this$static.m_RangeDecoder, posState)
      this$static.state = this$static.state < 7 ? 7 : 10
      posSlot = $Decode_0(
        this$static.m_PosSlotDecoder[GetLenToPosState(len)],
        this$static.m_RangeDecoder
      )
      if (posSlot >= 4) {
        numDirectBits = (posSlot >> 1) - 1
        this$static.rep0 = (2 | (posSlot & 1)) << numDirectBits
        if (posSlot < 14) {
          this$static.rep0 += ReverseDecode(
            this$static.m_PosDecoders,
            this$static.rep0 - posSlot - 1,
            this$static.m_RangeDecoder,
            numDirectBits
          )
        } else {
          this$static.rep0 +=
            $DecodeDirectBits(this$static.m_RangeDecoder, numDirectBits - 4) <<
            4
          this$static.rep0 += $ReverseDecode(
            this$static.m_PosAlignDecoder,
            this$static.m_RangeDecoder
          )
          if (this$static.rep0 < 0) {
            if (this$static.rep0 == -1) {
              return 1
            }
            return -1
          }
        }
      } else this$static.rep0 = posSlot
    }
    if (
      compare(fromInt(this$static.rep0), this$static.nowPos64) >= 0 ||
      this$static.rep0 >= this$static.m_DictionarySizeCheck
    ) {
      return -1
    }
    $CopyBlock(this$static.m_OutWindow, this$static.rep0, len)
    this$static.nowPos64 = add(this$static.nowPos64, fromInt(len))
    this$static.prevByte = $GetByte(this$static.m_OutWindow, 0)
  }
  return 0
}

function $Decoder(this$static) {
  this$static.m_OutWindow = {}
  this$static.m_RangeDecoder = {}
  this$static.m_IsMatchDecoders = initDim(192)
  this$static.m_IsRepDecoders = initDim(12)
  this$static.m_IsRepG0Decoders = initDim(12)
  this$static.m_IsRepG1Decoders = initDim(12)
  this$static.m_IsRepG2Decoders = initDim(12)
  this$static.m_IsRep0LongDecoders = initDim(192)
  this$static.m_PosSlotDecoder = initDim(4)
  this$static.m_PosDecoders = initDim(114)
  this$static.m_PosAlignDecoder = $BitTreeDecoder({}, 4)
  this$static.m_LenDecoder = $Decoder$LenDecoder({})
  this$static.m_RepLenDecoder = $Decoder$LenDecoder({})
  this$static.m_LiteralDecoder = {}
  for (var i = 0; i < 4; ++i) {
    this$static.m_PosSlotDecoder[i] = $BitTreeDecoder({}, 6)
  }
  return this$static
}

function $Init_1(this$static) {
  this$static.m_OutWindow._streamPos = 0
  this$static.m_OutWindow._pos = 0
  InitBitModels(this$static.m_IsMatchDecoders)
  InitBitModels(this$static.m_IsRep0LongDecoders)
  InitBitModels(this$static.m_IsRepDecoders)
  InitBitModels(this$static.m_IsRepG0Decoders)
  InitBitModels(this$static.m_IsRepG1Decoders)
  InitBitModels(this$static.m_IsRepG2Decoders)
  InitBitModels(this$static.m_PosDecoders)
  $Init_0(this$static.m_LiteralDecoder)
  for (var i = 0; i < 4; ++i) {
    InitBitModels(this$static.m_PosSlotDecoder[i].Models)
  }
  $Init(this$static.m_LenDecoder)
  $Init(this$static.m_RepLenDecoder)
  InitBitModels(this$static.m_PosAlignDecoder.Models)
  $Init_8(this$static.m_RangeDecoder)
}

function $SetDecoderProperties(this$static, properties) {
  var dictionarySize, i, lc, lp, pb, remainder, val
  if (properties.length < 5) return 0
  val = properties[0] & 255
  lc = val % 9
  remainder = ~~(val / 9)
  lp = remainder % 5
  pb = ~~(remainder / 5)
  dictionarySize = 0
  for (i = 0; i < 4; ++i) {
    dictionarySize += (properties[1 + i] & 255) << (i * 8)
  }
  // NOTE: If the input is bad, it might call for an insanely large dictionary size, which would crash the script.
  if (dictionarySize > 99999999 || !$SetLcLpPb(this$static, lc, lp, pb)) {
    return 0
  }
  return $SetDictionarySize(this$static, dictionarySize)
}

function $SetDictionarySize(this$static, dictionarySize) {
  if (dictionarySize < 0) {
    return 0
  }
  if (this$static.m_DictionarySize != dictionarySize) {
    this$static.m_DictionarySize = dictionarySize
    this$static.m_DictionarySizeCheck = Math.max(
      this$static.m_DictionarySize,
      1
    )
    $Create_5(
      this$static.m_OutWindow,
      Math.max(this$static.m_DictionarySizeCheck, 4096)
    )
  }
  return 1
}

function $SetLcLpPb(this$static, lc, lp, pb) {
  if (lc > 8 || lp > 4 || pb > 4) {
    return 0
  }
  $Create_0(this$static.m_LiteralDecoder, lp, lc)
  var numPosStates = 1 << pb
  $Create(this$static.m_LenDecoder, numPosStates)
  $Create(this$static.m_RepLenDecoder, numPosStates)
  this$static.m_PosStateMask = numPosStates - 1
  return 1
}

function $Create(this$static, numPosStates) {
  for (
    ;
    this$static.m_NumPosStates < numPosStates;
    ++this$static.m_NumPosStates
  ) {
    this$static.m_LowCoder[this$static.m_NumPosStates] = $BitTreeDecoder({}, 3)
    this$static.m_MidCoder[this$static.m_NumPosStates] = $BitTreeDecoder({}, 3)
  }
}

function $Decode(this$static, rangeDecoder, posState) {
  if (!$DecodeBit(rangeDecoder, this$static.m_Choice, 0)) {
    return $Decode_0(this$static.m_LowCoder[posState], rangeDecoder)
  }
  var symbol = 8
  if (!$DecodeBit(rangeDecoder, this$static.m_Choice, 1)) {
    symbol += $Decode_0(this$static.m_MidCoder[posState], rangeDecoder)
  } else {
    symbol += 8 + $Decode_0(this$static.m_HighCoder, rangeDecoder)
  }
  return symbol
}

function $Decoder$LenDecoder(this$static) {
  this$static.m_Choice = initDim(2)
  this$static.m_LowCoder = initDim(16)
  this$static.m_MidCoder = initDim(16)
  this$static.m_HighCoder = $BitTreeDecoder({}, 8)
  this$static.m_NumPosStates = 0
  return this$static
}

function $Init(this$static) {
  InitBitModels(this$static.m_Choice)
  for (var posState = 0; posState < this$static.m_NumPosStates; ++posState) {
    InitBitModels(this$static.m_LowCoder[posState].Models)
    InitBitModels(this$static.m_MidCoder[posState].Models)
  }
  InitBitModels(this$static.m_HighCoder.Models)
}

function $Create_0(this$static, numPosBits, numPrevBits) {
  var i, numStates
  if (
    this$static.m_Coders != null &&
    this$static.m_NumPrevBits == numPrevBits &&
    this$static.m_NumPosBits == numPosBits
  )
    return
  this$static.m_NumPosBits = numPosBits
  this$static.m_PosMask = (1 << numPosBits) - 1
  this$static.m_NumPrevBits = numPrevBits
  numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  this$static.m_Coders = initDim(numStates)
  for (i = 0; i < numStates; ++i)
    this$static.m_Coders[i] = $Decoder$LiteralDecoder$Decoder2({})
}

function $GetDecoder(this$static, pos, prevByte) {
  return this$static.m_Coders[
    ((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) +
      ((prevByte & 255) >>> (8 - this$static.m_NumPrevBits))
  ]
}

function $Init_0(this$static) {
  var i, numStates
  numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  for (i = 0; i < numStates; ++i) {
    InitBitModels(this$static.m_Coders[i].m_Decoders)
  }
}

function $DecodeNormal(this$static, rangeDecoder) {
  var symbol = 1
  do {
    symbol =
      (symbol << 1) | $DecodeBit(rangeDecoder, this$static.m_Decoders, symbol)
  } while (symbol < 256)
  return (symbol << 24) >> 24
}

function $DecodeWithMatchByte(this$static, rangeDecoder, matchByte) {
  var bit,
    matchBit,
    symbol = 1
  do {
    matchBit = (matchByte >> 7) & 1
    matchByte <<= 1
    bit = $DecodeBit(
      rangeDecoder,
      this$static.m_Decoders,
      ((1 + matchBit) << 8) + symbol
    )
    symbol = (symbol << 1) | bit
    if (matchBit != bit) {
      while (symbol < 256) {
        symbol =
          (symbol << 1) |
          $DecodeBit(rangeDecoder, this$static.m_Decoders, symbol)
      }
      break
    }
  } while (symbol < 256)
  return (symbol << 24) >> 24
}

function $Decoder$LiteralDecoder$Decoder2(this$static) {
  this$static.m_Decoders = initDim(768)
  return this$static
}
var g_FastPos = (function() {
  var j,
    k,
    slotFast,
    c = 2,
    g_FastPos = [0, 1]
  for (slotFast = 2; slotFast < 22; ++slotFast) {
    k = 1 << ((slotFast >> 1) - 1)
    for (j = 0; j < k; ++j, ++c) g_FastPos[c] = (slotFast << 24) >> 24
  }
  return g_FastPos
})()

function $Backward(this$static, cur) {
  var backCur, backMem, posMem, posPrev
  this$static._optimumEndIndex = cur
  posMem = this$static._optimum[cur].PosPrev
  backMem = this$static._optimum[cur].BackPrev
  do {
    if (this$static._optimum[cur].Prev1IsChar) {
      $MakeAsChar(this$static._optimum[posMem])
      this$static._optimum[posMem].PosPrev = posMem - 1
      if (this$static._optimum[cur].Prev2) {
        this$static._optimum[posMem - 1].Prev1IsChar = 0
        this$static._optimum[posMem - 1].PosPrev =
          this$static._optimum[cur].PosPrev2
        this$static._optimum[posMem - 1].BackPrev =
          this$static._optimum[cur].BackPrev2
      }
    }
    posPrev = posMem
    backCur = backMem
    backMem = this$static._optimum[posPrev].BackPrev
    posMem = this$static._optimum[posPrev].PosPrev
    this$static._optimum[posPrev].BackPrev = backCur
    this$static._optimum[posPrev].PosPrev = cur
    cur = posPrev
  } while (cur > 0)
  this$static.backRes = this$static._optimum[0].BackPrev
  this$static._optimumCurrentIndex = this$static._optimum[0].PosPrev
  return this$static._optimumCurrentIndex
}

function $BaseInit(this$static) {
  this$static._state = 0
  this$static._previousByte = 0
  for (var i = 0; i < 4; ++i) {
    this$static._repDistances[i] = 0
  }
}

function $CodeOneBlock(this$static, inSize, outSize, finished) {
  var baseVal,
    complexState,
    curByte,
    distance,
    footerBits,
    i,
    len,
    lenToPosState,
    matchByte,
    pos,
    posReduced,
    posSlot,
    posState,
    progressPosValuePrev,
    subCoder
  inSize[0] = P0_longLit
  outSize[0] = P0_longLit
  finished[0] = 1
  if (this$static._inStream) {
    this$static._matchFinder._stream = this$static._inStream
    $Init_5(this$static._matchFinder)
    this$static._needReleaseMFStream = 1
    this$static._inStream = null
  }
  if (this$static._finished) {
    return
  }
  this$static._finished = 1
  progressPosValuePrev = this$static.nowPos64
  if (eq(this$static.nowPos64, P0_longLit)) {
    if (!$GetNumAvailableBytes(this$static._matchFinder)) {
      $Flush(this$static, lowBits_0(this$static.nowPos64))
      return
    }
    $ReadMatchDistances(this$static)
    posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask
    $Encode_3(
      this$static._rangeEncoder,
      this$static._isMatch,
      (this$static._state << 4) + posState,
      0
    )
    this$static._state = StateUpdateChar(this$static._state)
    curByte = $GetIndexByte(
      this$static._matchFinder,
      -this$static._additionalOffset
    )
    $Encode_1(
      $GetSubCoder(
        this$static._literalEncoder,
        lowBits_0(this$static.nowPos64),
        this$static._previousByte
      ),
      this$static._rangeEncoder,
      curByte
    )
    this$static._previousByte = curByte
    --this$static._additionalOffset
    this$static.nowPos64 = add(this$static.nowPos64, P1_longLit)
  }
  if (!$GetNumAvailableBytes(this$static._matchFinder)) {
    $Flush(this$static, lowBits_0(this$static.nowPos64))
    return
  }
  while (1) {
    len = $GetOptimum(this$static, lowBits_0(this$static.nowPos64))
    pos = this$static.backRes
    posState = lowBits_0(this$static.nowPos64) & this$static._posStateMask
    complexState = (this$static._state << 4) + posState
    if (len == 1 && pos == -1) {
      $Encode_3(
        this$static._rangeEncoder,
        this$static._isMatch,
        complexState,
        0
      )
      curByte = $GetIndexByte(
        this$static._matchFinder,
        -this$static._additionalOffset
      )
      subCoder = $GetSubCoder(
        this$static._literalEncoder,
        lowBits_0(this$static.nowPos64),
        this$static._previousByte
      )
      if (this$static._state < 7) {
        $Encode_1(subCoder, this$static._rangeEncoder, curByte)
      } else {
        matchByte = $GetIndexByte(
          this$static._matchFinder,
          -this$static._repDistances[0] - 1 - this$static._additionalOffset
        )
        $EncodeMatched(subCoder, this$static._rangeEncoder, matchByte, curByte)
      }
      this$static._previousByte = curByte
      this$static._state = StateUpdateChar(this$static._state)
    } else {
      $Encode_3(
        this$static._rangeEncoder,
        this$static._isMatch,
        complexState,
        1
      )
      if (pos < 4) {
        $Encode_3(
          this$static._rangeEncoder,
          this$static._isRep,
          this$static._state,
          1
        )
        if (!pos) {
          $Encode_3(
            this$static._rangeEncoder,
            this$static._isRepG0,
            this$static._state,
            0
          )
          if (len == 1) {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRep0Long,
              complexState,
              0
            )
          } else {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRep0Long,
              complexState,
              1
            )
          }
        } else {
          $Encode_3(
            this$static._rangeEncoder,
            this$static._isRepG0,
            this$static._state,
            1
          )
          if (pos == 1) {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRepG1,
              this$static._state,
              0
            )
          } else {
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRepG1,
              this$static._state,
              1
            )
            $Encode_3(
              this$static._rangeEncoder,
              this$static._isRepG2,
              this$static._state,
              pos - 2
            )
          }
        }
        if (len == 1) {
          this$static._state = this$static._state < 7 ? 9 : 11
        } else {
          $Encode_0(
            this$static._repMatchLenEncoder,
            this$static._rangeEncoder,
            len - 2,
            posState
          )
          this$static._state = this$static._state < 7 ? 8 : 11
        }
        distance = this$static._repDistances[pos]
        if (pos != 0) {
          for (i = pos; i >= 1; --i) {
            this$static._repDistances[i] = this$static._repDistances[i - 1]
          }
          this$static._repDistances[0] = distance
        }
      } else {
        $Encode_3(
          this$static._rangeEncoder,
          this$static._isRep,
          this$static._state,
          0
        )
        this$static._state = this$static._state < 7 ? 7 : 10
        $Encode_0(
          this$static._lenEncoder,
          this$static._rangeEncoder,
          len - 2,
          posState
        )
        pos -= 4
        posSlot = GetPosSlot(pos)
        lenToPosState = GetLenToPosState(len)
        $Encode_2(
          this$static._posSlotEncoder[lenToPosState],
          this$static._rangeEncoder,
          posSlot
        )
        if (posSlot >= 4) {
          footerBits = (posSlot >> 1) - 1
          baseVal = (2 | (posSlot & 1)) << footerBits
          posReduced = pos - baseVal
          if (posSlot < 14) {
            ReverseEncode(
              this$static._posEncoders,
              baseVal - posSlot - 1,
              this$static._rangeEncoder,
              footerBits,
              posReduced
            )
          } else {
            $EncodeDirectBits(
              this$static._rangeEncoder,
              posReduced >> 4,
              footerBits - 4
            )
            $ReverseEncode(
              this$static._posAlignEncoder,
              this$static._rangeEncoder,
              posReduced & 15
            )
            ++this$static._alignPriceCount
          }
        }
        distance = pos
        for (i = 3; i >= 1; --i) {
          this$static._repDistances[i] = this$static._repDistances[i - 1]
        }
        this$static._repDistances[0] = distance
        ++this$static._matchPriceCount
      }
      this$static._previousByte = $GetIndexByte(
        this$static._matchFinder,
        len - 1 - this$static._additionalOffset
      )
    }
    this$static._additionalOffset -= len
    this$static.nowPos64 = add(this$static.nowPos64, fromInt(len))
    if (!this$static._additionalOffset) {
      if (this$static._matchPriceCount >= 128) {
        $FillDistancesPrices(this$static)
      }
      if (this$static._alignPriceCount >= 16) {
        $FillAlignPrices(this$static)
      }
      inSize[0] = this$static.nowPos64
      outSize[0] = $GetProcessedSizeAdd(this$static._rangeEncoder)
      if (!$GetNumAvailableBytes(this$static._matchFinder)) {
        $Flush(this$static, lowBits_0(this$static.nowPos64))
        return
      }
      if (
        compare(sub(this$static.nowPos64, progressPosValuePrev), [4096, 0]) >= 0
      ) {
        this$static._finished = 0
        finished[0] = 0
        return
      }
    }
  }
}

function $Create_2(this$static) {
  var bt, numHashBytes
  if (!this$static._matchFinder) {
    bt = {}
    numHashBytes = 4
    if (!this$static._matchFinderType) {
      numHashBytes = 2
    }
    $SetType(bt, numHashBytes)
    this$static._matchFinder = bt
  }
  $Create_1(
    this$static._literalEncoder,
    this$static._numLiteralPosStateBits,
    this$static._numLiteralContextBits
  )
  if (
    this$static._dictionarySize == this$static._dictionarySizePrev &&
    this$static._numFastBytesPrev == this$static._numFastBytes
  ) {
    return
  }
  $Create_3(
    this$static._matchFinder,
    this$static._dictionarySize,
    4096,
    this$static._numFastBytes,
    274
  )
  this$static._dictionarySizePrev = this$static._dictionarySize
  this$static._numFastBytesPrev = this$static._numFastBytes
}

function $Encoder(this$static) {
  var i
  this$static._repDistances = initDim(4)
  this$static._optimum = []
  this$static._rangeEncoder = {}
  this$static._isMatch = initDim(192)
  this$static._isRep = initDim(12)
  this$static._isRepG0 = initDim(12)
  this$static._isRepG1 = initDim(12)
  this$static._isRepG2 = initDim(12)
  this$static._isRep0Long = initDim(192)
  this$static._posSlotEncoder = []
  this$static._posEncoders = initDim(114)
  this$static._posAlignEncoder = $BitTreeEncoder({}, 4)
  this$static._lenEncoder = $Encoder$LenPriceTableEncoder({})
  this$static._repMatchLenEncoder = $Encoder$LenPriceTableEncoder({})
  this$static._literalEncoder = {}
  this$static._matchDistances = []
  this$static._posSlotPrices = []
  this$static._distancesPrices = []
  this$static._alignPrices = initDim(16)
  this$static.reps = initDim(4)
  this$static.repLens = initDim(4)
  this$static.processedInSize = [P0_longLit]
  this$static.processedOutSize = [P0_longLit]
  this$static.finished = [0]
  this$static.properties = initDim(5)
  this$static.tempPrices = initDim(128)
  this$static._longestMatchLength = 0
  this$static._matchFinderType = 1
  this$static._numDistancePairs = 0
  this$static._numFastBytesPrev = -1
  this$static.backRes = 0
  for (i = 0; i < 4096; ++i) {
    this$static._optimum[i] = {}
  }
  for (i = 0; i < 4; ++i) {
    this$static._posSlotEncoder[i] = $BitTreeEncoder({}, 6)
  }
  return this$static
}

function $FillAlignPrices(this$static) {
  for (var i = 0; i < 16; ++i) {
    this$static._alignPrices[i] = $ReverseGetPrice(
      this$static._posAlignEncoder,
      i
    )
  }
  this$static._alignPriceCount = 0
}

function $FillDistancesPrices(this$static) {
  var baseVal, encoder, footerBits, i, lenToPosState, posSlot, st, st2
  for (i = 4; i < 128; ++i) {
    posSlot = GetPosSlot(i)
    footerBits = (posSlot >> 1) - 1
    baseVal = (2 | (posSlot & 1)) << footerBits
    this$static.tempPrices[i] = ReverseGetPrice(
      this$static._posEncoders,
      baseVal - posSlot - 1,
      footerBits,
      i - baseVal
    )
  }
  for (lenToPosState = 0; lenToPosState < 4; ++lenToPosState) {
    encoder = this$static._posSlotEncoder[lenToPosState]
    st = lenToPosState << 6
    for (posSlot = 0; posSlot < this$static._distTableSize; ++posSlot) {
      this$static._posSlotPrices[st + posSlot] = $GetPrice_1(encoder, posSlot)
    }
    for (posSlot = 14; posSlot < this$static._distTableSize; ++posSlot) {
      this$static._posSlotPrices[st + posSlot] += ((posSlot >> 1) - 1 - 4) << 6
    }
    st2 = lenToPosState * 128
    for (i = 0; i < 4; ++i) {
      this$static._distancesPrices[st2 + i] = this$static._posSlotPrices[st + i]
    }
    for (; i < 128; ++i) {
      this$static._distancesPrices[st2 + i] =
        this$static._posSlotPrices[st + GetPosSlot(i)] +
        this$static.tempPrices[i]
    }
  }
  this$static._matchPriceCount = 0
}

function $Flush(this$static, nowPos) {
  $ReleaseMFStream(this$static)
  $WriteEndMarker(this$static, nowPos & this$static._posStateMask)
  for (var i = 0; i < 5; ++i) {
    $ShiftLow(this$static._rangeEncoder)
  }
}

function $GetOptimum(this$static, position) {
  var cur,
    curAnd1Price,
    curAndLenCharPrice,
    curAndLenPrice,
    curBack,
    curPrice,
    currentByte,
    distance,
    i,
    len,
    lenEnd,
    lenMain,
    lenRes,
    lenTest,
    lenTest2,
    lenTestTemp,
    matchByte,
    matchPrice,
    newLen,
    nextIsChar,
    nextMatchPrice,
    nextOptimum,
    nextRepMatchPrice,
    normalMatchPrice,
    numAvailableBytes,
    numAvailableBytesFull,
    numDistancePairs,
    offs,
    offset,
    opt,
    optimum,
    pos,
    posPrev,
    posState,
    posStateNext,
    price_4,
    repIndex,
    repLen,
    repMatchPrice,
    repMaxIndex,
    shortRepPrice,
    startLen,
    state,
    state2,
    t,
    price,
    price_0,
    price_1,
    price_2,
    price_3
  if (this$static._optimumEndIndex != this$static._optimumCurrentIndex) {
    lenRes =
      this$static._optimum[this$static._optimumCurrentIndex].PosPrev -
      this$static._optimumCurrentIndex
    this$static.backRes =
      this$static._optimum[this$static._optimumCurrentIndex].BackPrev
    this$static._optimumCurrentIndex =
      this$static._optimum[this$static._optimumCurrentIndex].PosPrev
    return lenRes
  }
  this$static._optimumCurrentIndex = this$static._optimumEndIndex = 0
  if (this$static._longestMatchWasFound) {
    lenMain = this$static._longestMatchLength
    this$static._longestMatchWasFound = 0
  } else {
    lenMain = $ReadMatchDistances(this$static)
  }
  numDistancePairs = this$static._numDistancePairs
  numAvailableBytes = $GetNumAvailableBytes(this$static._matchFinder) + 1
  if (numAvailableBytes < 2) {
    this$static.backRes = -1
    return 1
  }
  if (numAvailableBytes > 273) {
    numAvailableBytes = 273
  }
  repMaxIndex = 0
  for (i = 0; i < 4; ++i) {
    this$static.reps[i] = this$static._repDistances[i]
    this$static.repLens[i] = $GetMatchLen(
      this$static._matchFinder,
      -1,
      this$static.reps[i],
      273
    )
    if (this$static.repLens[i] > this$static.repLens[repMaxIndex]) {
      repMaxIndex = i
    }
  }
  if (this$static.repLens[repMaxIndex] >= this$static._numFastBytes) {
    this$static.backRes = repMaxIndex
    lenRes = this$static.repLens[repMaxIndex]
    $MovePos(this$static, lenRes - 1)
    return lenRes
  }
  if (lenMain >= this$static._numFastBytes) {
    this$static.backRes = this$static._matchDistances[numDistancePairs - 1] + 4
    $MovePos(this$static, lenMain - 1)
    return lenMain
  }
  currentByte = $GetIndexByte(this$static._matchFinder, -1)
  matchByte = $GetIndexByte(
    this$static._matchFinder,
    -this$static._repDistances[0] - 1 - 1
  )
  if (
    lenMain < 2 &&
    currentByte != matchByte &&
    this$static.repLens[repMaxIndex] < 2
  ) {
    this$static.backRes = -1
    return 1
  }
  this$static._optimum[0].State = this$static._state
  posState = position & this$static._posStateMask
  this$static._optimum[1].Price =
    ProbPrices[
      this$static._isMatch[(this$static._state << 4) + posState] >>> 2
    ] +
    $GetPrice_0(
      $GetSubCoder(
        this$static._literalEncoder,
        position,
        this$static._previousByte
      ),
      this$static._state >= 7,
      matchByte,
      currentByte
    )
  $MakeAsChar(this$static._optimum[1])
  matchPrice =
    ProbPrices[
      (2048 - this$static._isMatch[(this$static._state << 4) + posState]) >>> 2
    ]
  repMatchPrice =
    matchPrice +
    ProbPrices[(2048 - this$static._isRep[this$static._state]) >>> 2]
  if (matchByte == currentByte) {
    shortRepPrice =
      repMatchPrice +
      $GetRepLen1Price(this$static, this$static._state, posState)
    if (shortRepPrice < this$static._optimum[1].Price) {
      this$static._optimum[1].Price = shortRepPrice
      $MakeAsShortRep(this$static._optimum[1])
    }
  }
  lenEnd =
    lenMain >= this$static.repLens[repMaxIndex]
      ? lenMain
      : this$static.repLens[repMaxIndex]
  if (lenEnd < 2) {
    this$static.backRes = this$static._optimum[1].BackPrev
    return 1
  }
  this$static._optimum[1].PosPrev = 0
  this$static._optimum[0].Backs0 = this$static.reps[0]
  this$static._optimum[0].Backs1 = this$static.reps[1]
  this$static._optimum[0].Backs2 = this$static.reps[2]
  this$static._optimum[0].Backs3 = this$static.reps[3]
  len = lenEnd
  do {
    this$static._optimum[len--].Price = 268435455
  } while (len >= 2)
  for (i = 0; i < 4; ++i) {
    repLen = this$static.repLens[i]
    if (repLen < 2) {
      continue
    }
    price_4 =
      repMatchPrice +
      $GetPureRepPrice(this$static, i, this$static._state, posState)
    do {
      curAndLenPrice =
        price_4 +
        $GetPrice(this$static._repMatchLenEncoder, repLen - 2, posState)
      optimum = this$static._optimum[repLen]
      if (curAndLenPrice < optimum.Price) {
        optimum.Price = curAndLenPrice
        optimum.PosPrev = 0
        optimum.BackPrev = i
        optimum.Prev1IsChar = 0
      }
    } while (--repLen >= 2)
  }
  normalMatchPrice =
    matchPrice + ProbPrices[this$static._isRep[this$static._state] >>> 2]
  len = this$static.repLens[0] >= 2 ? this$static.repLens[0] + 1 : 2
  if (len <= lenMain) {
    offs = 0
    while (len > this$static._matchDistances[offs]) {
      offs += 2
    }
    for (; ; ++len) {
      distance = this$static._matchDistances[offs + 1]
      curAndLenPrice =
        normalMatchPrice + $GetPosLenPrice(this$static, distance, len, posState)
      optimum = this$static._optimum[len]
      if (curAndLenPrice < optimum.Price) {
        optimum.Price = curAndLenPrice
        optimum.PosPrev = 0
        optimum.BackPrev = distance + 4
        optimum.Prev1IsChar = 0
      }
      if (len == this$static._matchDistances[offs]) {
        offs += 2
        if (offs == numDistancePairs) {
          break
        }
      }
    }
  }
  cur = 0
  while (1) {
    ++cur
    if (cur == lenEnd) {
      return $Backward(this$static, cur)
    }
    newLen = $ReadMatchDistances(this$static)
    numDistancePairs = this$static._numDistancePairs
    if (newLen >= this$static._numFastBytes) {
      this$static._longestMatchLength = newLen
      this$static._longestMatchWasFound = 1
      return $Backward(this$static, cur)
    }
    ++position
    posPrev = this$static._optimum[cur].PosPrev
    if (this$static._optimum[cur].Prev1IsChar) {
      --posPrev
      if (this$static._optimum[cur].Prev2) {
        state = this$static._optimum[this$static._optimum[cur].PosPrev2].State
        if (this$static._optimum[cur].BackPrev2 < 4) {
          state = state < 7 ? 8 : 11
        } else {
          state = state < 7 ? 7 : 10
        }
      } else {
        state = this$static._optimum[posPrev].State
      }
      state = StateUpdateChar(state)
    } else {
      state = this$static._optimum[posPrev].State
    }
    if (posPrev == cur - 1) {
      if (!this$static._optimum[cur].BackPrev) {
        state = state < 7 ? 9 : 11
      } else {
        state = StateUpdateChar(state)
      }
    } else {
      if (
        this$static._optimum[cur].Prev1IsChar &&
        this$static._optimum[cur].Prev2
      ) {
        posPrev = this$static._optimum[cur].PosPrev2
        pos = this$static._optimum[cur].BackPrev2
        state = state < 7 ? 8 : 11
      } else {
        pos = this$static._optimum[cur].BackPrev
        if (pos < 4) {
          state = state < 7 ? 8 : 11
        } else {
          state = state < 7 ? 7 : 10
        }
      }
      opt = this$static._optimum[posPrev]
      if (pos < 4) {
        if (!pos) {
          this$static.reps[0] = opt.Backs0
          this$static.reps[1] = opt.Backs1
          this$static.reps[2] = opt.Backs2
          this$static.reps[3] = opt.Backs3
        } else if (pos == 1) {
          this$static.reps[0] = opt.Backs1
          this$static.reps[1] = opt.Backs0
          this$static.reps[2] = opt.Backs2
          this$static.reps[3] = opt.Backs3
        } else if (pos == 2) {
          this$static.reps[0] = opt.Backs2
          this$static.reps[1] = opt.Backs0
          this$static.reps[2] = opt.Backs1
          this$static.reps[3] = opt.Backs3
        } else {
          this$static.reps[0] = opt.Backs3
          this$static.reps[1] = opt.Backs0
          this$static.reps[2] = opt.Backs1
          this$static.reps[3] = opt.Backs2
        }
      } else {
        this$static.reps[0] = pos - 4
        this$static.reps[1] = opt.Backs0
        this$static.reps[2] = opt.Backs1
        this$static.reps[3] = opt.Backs2
      }
    }
    this$static._optimum[cur].State = state
    this$static._optimum[cur].Backs0 = this$static.reps[0]
    this$static._optimum[cur].Backs1 = this$static.reps[1]
    this$static._optimum[cur].Backs2 = this$static.reps[2]
    this$static._optimum[cur].Backs3 = this$static.reps[3]
    curPrice = this$static._optimum[cur].Price
    currentByte = $GetIndexByte(this$static._matchFinder, -1)
    matchByte = $GetIndexByte(
      this$static._matchFinder,
      -this$static.reps[0] - 1 - 1
    )
    posState = position & this$static._posStateMask
    curAnd1Price =
      curPrice +
      ProbPrices[this$static._isMatch[(state << 4) + posState] >>> 2] +
      $GetPrice_0(
        $GetSubCoder(
          this$static._literalEncoder,
          position,
          $GetIndexByte(this$static._matchFinder, -2)
        ),
        state >= 7,
        matchByte,
        currentByte
      )
    nextOptimum = this$static._optimum[cur + 1]
    nextIsChar = 0
    if (curAnd1Price < nextOptimum.Price) {
      nextOptimum.Price = curAnd1Price
      nextOptimum.PosPrev = cur
      nextOptimum.BackPrev = -1
      nextOptimum.Prev1IsChar = 0
      nextIsChar = 1
    }
    matchPrice =
      curPrice +
      ProbPrices[(2048 - this$static._isMatch[(state << 4) + posState]) >>> 2]
    repMatchPrice =
      matchPrice + ProbPrices[(2048 - this$static._isRep[state]) >>> 2]
    if (
      matchByte == currentByte &&
      !(nextOptimum.PosPrev < cur && !nextOptimum.BackPrev)
    ) {
      shortRepPrice =
        repMatchPrice +
        (ProbPrices[this$static._isRepG0[state] >>> 2] +
          ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2])
      if (shortRepPrice <= nextOptimum.Price) {
        nextOptimum.Price = shortRepPrice
        nextOptimum.PosPrev = cur
        nextOptimum.BackPrev = 0
        nextOptimum.Prev1IsChar = 0
        nextIsChar = 1
      }
    }
    numAvailableBytesFull = $GetNumAvailableBytes(this$static._matchFinder) + 1
    numAvailableBytesFull =
      4095 - cur < numAvailableBytesFull ? 4095 - cur : numAvailableBytesFull
    numAvailableBytes = numAvailableBytesFull
    if (numAvailableBytes < 2) {
      continue
    }
    if (numAvailableBytes > this$static._numFastBytes) {
      numAvailableBytes = this$static._numFastBytes
    }
    if (!nextIsChar && matchByte != currentByte) {
      t = Math.min(numAvailableBytesFull - 1, this$static._numFastBytes)
      lenTest2 = $GetMatchLen(
        this$static._matchFinder,
        0,
        this$static.reps[0],
        t
      )
      if (lenTest2 >= 2) {
        state2 = StateUpdateChar(state)
        posStateNext = (position + 1) & this$static._posStateMask
        nextRepMatchPrice =
          curAnd1Price +
          ProbPrices[
            (2048 - this$static._isMatch[(state2 << 4) + posStateNext]) >>> 2
          ] +
          ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
        offset = cur + 1 + lenTest2
        while (lenEnd < offset) {
          this$static._optimum[++lenEnd].Price = 268435455
        }
        curAndLenPrice =
          nextRepMatchPrice +
          ((price = $GetPrice(
            this$static._repMatchLenEncoder,
            lenTest2 - 2,
            posStateNext
          )),
          price + $GetPureRepPrice(this$static, 0, state2, posStateNext))
        optimum = this$static._optimum[offset]
        if (curAndLenPrice < optimum.Price) {
          optimum.Price = curAndLenPrice
          optimum.PosPrev = cur + 1
          optimum.BackPrev = 0
          optimum.Prev1IsChar = 1
          optimum.Prev2 = 0
        }
      }
    }
    startLen = 2
    for (repIndex = 0; repIndex < 4; ++repIndex) {
      lenTest = $GetMatchLen(
        this$static._matchFinder,
        -1,
        this$static.reps[repIndex],
        numAvailableBytes
      )
      if (lenTest < 2) {
        continue
      }
      lenTestTemp = lenTest
      do {
        while (lenEnd < cur + lenTest) {
          this$static._optimum[++lenEnd].Price = 268435455
        }
        curAndLenPrice =
          repMatchPrice +
          ((price_0 = $GetPrice(
            this$static._repMatchLenEncoder,
            lenTest - 2,
            posState
          )),
          price_0 + $GetPureRepPrice(this$static, repIndex, state, posState))
        optimum = this$static._optimum[cur + lenTest]
        if (curAndLenPrice < optimum.Price) {
          optimum.Price = curAndLenPrice
          optimum.PosPrev = cur
          optimum.BackPrev = repIndex
          optimum.Prev1IsChar = 0
        }
      } while (--lenTest >= 2)
      lenTest = lenTestTemp
      if (!repIndex) {
        startLen = lenTest + 1
      }
      if (lenTest < numAvailableBytesFull) {
        t = Math.min(
          numAvailableBytesFull - 1 - lenTest,
          this$static._numFastBytes
        )
        lenTest2 = $GetMatchLen(
          this$static._matchFinder,
          lenTest,
          this$static.reps[repIndex],
          t
        )
        if (lenTest2 >= 2) {
          state2 = state < 7 ? 8 : 11
          posStateNext = (position + lenTest) & this$static._posStateMask
          curAndLenCharPrice =
            repMatchPrice +
            ((price_1 = $GetPrice(
              this$static._repMatchLenEncoder,
              lenTest - 2,
              posState
            )),
            price_1 +
              $GetPureRepPrice(this$static, repIndex, state, posState)) +
            ProbPrices[
              this$static._isMatch[(state2 << 4) + posStateNext] >>> 2
            ] +
            $GetPrice_0(
              $GetSubCoder(
                this$static._literalEncoder,
                position + lenTest,
                $GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)
              ),
              1,
              $GetIndexByte(
                this$static._matchFinder,
                lenTest - 1 - (this$static.reps[repIndex] + 1)
              ),
              $GetIndexByte(this$static._matchFinder, lenTest - 1)
            )
          state2 = StateUpdateChar(state2)
          posStateNext = (position + lenTest + 1) & this$static._posStateMask
          nextMatchPrice =
            curAndLenCharPrice +
            ProbPrices[
              (2048 - this$static._isMatch[(state2 << 4) + posStateNext]) >>> 2
            ]
          nextRepMatchPrice =
            nextMatchPrice +
            ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
          offset = lenTest + 1 + lenTest2
          while (lenEnd < cur + offset) {
            this$static._optimum[++lenEnd].Price = 268435455
          }
          curAndLenPrice =
            nextRepMatchPrice +
            ((price_2 = $GetPrice(
              this$static._repMatchLenEncoder,
              lenTest2 - 2,
              posStateNext
            )),
            price_2 + $GetPureRepPrice(this$static, 0, state2, posStateNext))
          optimum = this$static._optimum[cur + offset]
          if (curAndLenPrice < optimum.Price) {
            optimum.Price = curAndLenPrice
            optimum.PosPrev = cur + lenTest + 1
            optimum.BackPrev = 0
            optimum.Prev1IsChar = 1
            optimum.Prev2 = 1
            optimum.PosPrev2 = cur
            optimum.BackPrev2 = repIndex
          }
        }
      }
    }
    if (newLen > numAvailableBytes) {
      newLen = numAvailableBytes
      for (
        numDistancePairs = 0;
        newLen > this$static._matchDistances[numDistancePairs];
        numDistancePairs += 2
      ) {}
      this$static._matchDistances[numDistancePairs] = newLen
      numDistancePairs += 2
    }
    if (newLen >= startLen) {
      normalMatchPrice =
        matchPrice + ProbPrices[this$static._isRep[state] >>> 2]
      while (lenEnd < cur + newLen) {
        this$static._optimum[++lenEnd].Price = 268435455
      }
      offs = 0
      while (startLen > this$static._matchDistances[offs]) {
        offs += 2
      }
      for (lenTest = startLen; ; ++lenTest) {
        curBack = this$static._matchDistances[offs + 1]
        curAndLenPrice =
          normalMatchPrice +
          $GetPosLenPrice(this$static, curBack, lenTest, posState)
        optimum = this$static._optimum[cur + lenTest]
        if (curAndLenPrice < optimum.Price) {
          optimum.Price = curAndLenPrice
          optimum.PosPrev = cur
          optimum.BackPrev = curBack + 4
          optimum.Prev1IsChar = 0
        }
        if (lenTest == this$static._matchDistances[offs]) {
          if (lenTest < numAvailableBytesFull) {
            t = Math.min(
              numAvailableBytesFull - 1 - lenTest,
              this$static._numFastBytes
            )
            lenTest2 = $GetMatchLen(
              this$static._matchFinder,
              lenTest,
              curBack,
              t
            )
            if (lenTest2 >= 2) {
              state2 = state < 7 ? 7 : 10
              posStateNext = (position + lenTest) & this$static._posStateMask
              curAndLenCharPrice =
                curAndLenPrice +
                ProbPrices[
                  this$static._isMatch[(state2 << 4) + posStateNext] >>> 2
                ] +
                $GetPrice_0(
                  $GetSubCoder(
                    this$static._literalEncoder,
                    position + lenTest,
                    $GetIndexByte(this$static._matchFinder, lenTest - 1 - 1)
                  ),
                  1,
                  $GetIndexByte(
                    this$static._matchFinder,
                    lenTest - (curBack + 1) - 1
                  ),
                  $GetIndexByte(this$static._matchFinder, lenTest - 1)
                )
              state2 = StateUpdateChar(state2)
              posStateNext =
                (position + lenTest + 1) & this$static._posStateMask
              nextMatchPrice =
                curAndLenCharPrice +
                ProbPrices[
                  (2048 -
                    this$static._isMatch[(state2 << 4) + posStateNext]) >>>
                    2
                ]
              nextRepMatchPrice =
                nextMatchPrice +
                ProbPrices[(2048 - this$static._isRep[state2]) >>> 2]
              offset = lenTest + 1 + lenTest2
              while (lenEnd < cur + offset) {
                this$static._optimum[++lenEnd].Price = 268435455
              }
              curAndLenPrice =
                nextRepMatchPrice +
                ((price_3 = $GetPrice(
                  this$static._repMatchLenEncoder,
                  lenTest2 - 2,
                  posStateNext
                )),
                price_3 +
                  $GetPureRepPrice(this$static, 0, state2, posStateNext))
              optimum = this$static._optimum[cur + offset]
              if (curAndLenPrice < optimum.Price) {
                optimum.Price = curAndLenPrice
                optimum.PosPrev = cur + lenTest + 1
                optimum.BackPrev = 0
                optimum.Prev1IsChar = 1
                optimum.Prev2 = 1
                optimum.PosPrev2 = cur
                optimum.BackPrev2 = curBack + 4
              }
            }
          }
          offs += 2
          if (offs == numDistancePairs) break
        }
      }
    }
  }
}

function $GetPosLenPrice(this$static, pos, len, posState) {
  var price,
    lenToPosState = GetLenToPosState(len)
  if (pos < 128) {
    price = this$static._distancesPrices[lenToPosState * 128 + pos]
  } else {
    price =
      this$static._posSlotPrices[(lenToPosState << 6) + GetPosSlot2(pos)] +
      this$static._alignPrices[pos & 15]
  }
  return price + $GetPrice(this$static._lenEncoder, len - 2, posState)
}

function $GetPureRepPrice(this$static, repIndex, state, posState) {
  var price
  if (!repIndex) {
    price = ProbPrices[this$static._isRepG0[state] >>> 2]
    price +=
      ProbPrices[
        (2048 - this$static._isRep0Long[(state << 4) + posState]) >>> 2
      ]
  } else {
    price = ProbPrices[(2048 - this$static._isRepG0[state]) >>> 2]
    if (repIndex == 1) {
      price += ProbPrices[this$static._isRepG1[state] >>> 2]
    } else {
      price += ProbPrices[(2048 - this$static._isRepG1[state]) >>> 2]
      price += GetPrice(this$static._isRepG2[state], repIndex - 2)
    }
  }
  return price
}

function $GetRepLen1Price(this$static, state, posState) {
  return (
    ProbPrices[this$static._isRepG0[state] >>> 2] +
    ProbPrices[this$static._isRep0Long[(state << 4) + posState] >>> 2]
  )
}

function $Init_4(this$static) {
  $BaseInit(this$static)
  $Init_9(this$static._rangeEncoder)
  InitBitModels(this$static._isMatch)
  InitBitModels(this$static._isRep0Long)
  InitBitModels(this$static._isRep)
  InitBitModels(this$static._isRepG0)
  InitBitModels(this$static._isRepG1)
  InitBitModels(this$static._isRepG2)
  InitBitModels(this$static._posEncoders)
  $Init_3(this$static._literalEncoder)
  for (var i = 0; i < 4; ++i) {
    InitBitModels(this$static._posSlotEncoder[i].Models)
  }
  $Init_2(this$static._lenEncoder, 1 << this$static._posStateBits)
  $Init_2(this$static._repMatchLenEncoder, 1 << this$static._posStateBits)
  InitBitModels(this$static._posAlignEncoder.Models)
  this$static._longestMatchWasFound = 0
  this$static._optimumEndIndex = 0
  this$static._optimumCurrentIndex = 0
  this$static._additionalOffset = 0
}

function $MovePos(this$static, num) {
  if (num > 0) {
    $Skip(this$static._matchFinder, num)
    this$static._additionalOffset += num
  }
}

function $ReadMatchDistances(this$static) {
  var lenRes = 0
  this$static._numDistancePairs = $GetMatches(
    this$static._matchFinder,
    this$static._matchDistances
  )
  if (this$static._numDistancePairs > 0) {
    lenRes = this$static._matchDistances[this$static._numDistancePairs - 2]
    if (lenRes == this$static._numFastBytes)
      lenRes += $GetMatchLen(
        this$static._matchFinder,
        lenRes - 1,
        this$static._matchDistances[this$static._numDistancePairs - 1],
        273 - lenRes
      )
  }
  ++this$static._additionalOffset
  return lenRes
}

function $ReleaseMFStream(this$static) {
  if (this$static._matchFinder && this$static._needReleaseMFStream) {
    this$static._matchFinder._stream = null
    this$static._needReleaseMFStream = 0
  }
}

function $ReleaseStreams(this$static) {
  $ReleaseMFStream(this$static)
  this$static._rangeEncoder.Stream = null
}

function $SetDictionarySize_0(this$static, dictionarySize) {
  this$static._dictionarySize = dictionarySize
  for (var dicLogSize = 0; dictionarySize > 1 << dicLogSize; ++dicLogSize) {}
  this$static._distTableSize = dicLogSize * 2
}

function $SetMatchFinder(this$static, matchFinderIndex) {
  var matchFinderIndexPrev = this$static._matchFinderType
  this$static._matchFinderType = matchFinderIndex
  if (
    this$static._matchFinder &&
    matchFinderIndexPrev != this$static._matchFinderType
  ) {
    this$static._dictionarySizePrev = -1
    this$static._matchFinder = null
  }
}

function $WriteCoderProperties(this$static, outStream) {
  this$static.properties[0] =
    (((this$static._posStateBits * 5 + this$static._numLiteralPosStateBits) *
      9 +
      this$static._numLiteralContextBits) <<
      24) >>
    24
  for (var i = 0; i < 4; ++i) {
    this$static.properties[1 + i] =
      ((this$static._dictionarySize >> (8 * i)) << 24) >> 24
  }
  $write_0(outStream, this$static.properties, 0, 5)
}

function $WriteEndMarker(this$static, posState) {
  if (!this$static._writeEndMark) {
    return
  }
  $Encode_3(
    this$static._rangeEncoder,
    this$static._isMatch,
    (this$static._state << 4) + posState,
    1
  )
  $Encode_3(
    this$static._rangeEncoder,
    this$static._isRep,
    this$static._state,
    0
  )
  this$static._state = this$static._state < 7 ? 7 : 10
  $Encode_0(this$static._lenEncoder, this$static._rangeEncoder, 0, posState)
  var lenToPosState = GetLenToPosState(2)
  $Encode_2(
    this$static._posSlotEncoder[lenToPosState],
    this$static._rangeEncoder,
    63
  )
  $EncodeDirectBits(this$static._rangeEncoder, 67108863, 26)
  $ReverseEncode(this$static._posAlignEncoder, this$static._rangeEncoder, 15)
}

function GetPosSlot(pos) {
  if (pos < 2048) {
    return g_FastPos[pos]
  }
  if (pos < 2097152) {
    return g_FastPos[pos >> 10] + 20
  }
  return g_FastPos[pos >> 20] + 40
}

function GetPosSlot2(pos) {
  if (pos < 131072) {
    return g_FastPos[pos >> 6] + 12
  }
  if (pos < 134217728) {
    return g_FastPos[pos >> 16] + 32
  }
  return g_FastPos[pos >> 26] + 52
}

function $Encode(this$static, rangeEncoder, symbol, posState) {
  if (symbol < 8) {
    $Encode_3(rangeEncoder, this$static._choice, 0, 0)
    $Encode_2(this$static._lowCoder[posState], rangeEncoder, symbol)
  } else {
    symbol -= 8
    $Encode_3(rangeEncoder, this$static._choice, 0, 1)
    if (symbol < 8) {
      $Encode_3(rangeEncoder, this$static._choice, 1, 0)
      $Encode_2(this$static._midCoder[posState], rangeEncoder, symbol)
    } else {
      $Encode_3(rangeEncoder, this$static._choice, 1, 1)
      $Encode_2(this$static._highCoder, rangeEncoder, symbol - 8)
    }
  }
}

function $Encoder$LenEncoder(this$static) {
  this$static._choice = initDim(2)
  this$static._lowCoder = initDim(16)
  this$static._midCoder = initDim(16)
  this$static._highCoder = $BitTreeEncoder({}, 8)
  for (var posState = 0; posState < 16; ++posState) {
    this$static._lowCoder[posState] = $BitTreeEncoder({}, 3)
    this$static._midCoder[posState] = $BitTreeEncoder({}, 3)
  }
  return this$static
}

function $Init_2(this$static, numPosStates) {
  InitBitModels(this$static._choice)
  for (var posState = 0; posState < numPosStates; ++posState) {
    InitBitModels(this$static._lowCoder[posState].Models)
    InitBitModels(this$static._midCoder[posState].Models)
  }
  InitBitModels(this$static._highCoder.Models)
}

function $SetPrices(this$static, posState, numSymbols, prices, st) {
  var a0, a1, b0, b1, i
  a0 = ProbPrices[this$static._choice[0] >>> 2]
  a1 = ProbPrices[(2048 - this$static._choice[0]) >>> 2]
  b0 = a1 + ProbPrices[this$static._choice[1] >>> 2]
  b1 = a1 + ProbPrices[(2048 - this$static._choice[1]) >>> 2]
  i = 0
  for (i = 0; i < 8; ++i) {
    if (i >= numSymbols) return
    prices[st + i] = a0 + $GetPrice_1(this$static._lowCoder[posState], i)
  }
  for (; i < 16; ++i) {
    if (i >= numSymbols) return
    prices[st + i] = b0 + $GetPrice_1(this$static._midCoder[posState], i - 8)
  }
  for (; i < numSymbols; ++i) {
    prices[st + i] = b1 + $GetPrice_1(this$static._highCoder, i - 8 - 8)
  }
}

function $Encode_0(this$static, rangeEncoder, symbol, posState) {
  $Encode(this$static, rangeEncoder, symbol, posState)
  if (--this$static._counters[posState] == 0) {
    $SetPrices(
      this$static,
      posState,
      this$static._tableSize,
      this$static._prices,
      posState * 272
    )
    this$static._counters[posState] = this$static._tableSize
  }
}

function $Encoder$LenPriceTableEncoder(this$static) {
  $Encoder$LenEncoder(this$static)
  this$static._prices = []
  this$static._counters = []
  return this$static
}

function $GetPrice(this$static, symbol, posState) {
  return this$static._prices[posState * 272 + symbol]
}

function $UpdateTables(this$static, numPosStates) {
  for (var posState = 0; posState < numPosStates; ++posState) {
    $SetPrices(
      this$static,
      posState,
      this$static._tableSize,
      this$static._prices,
      posState * 272
    )
    this$static._counters[posState] = this$static._tableSize
  }
}

function $Create_1(this$static, numPosBits, numPrevBits) {
  var i, numStates
  if (
    this$static.m_Coders != null &&
    this$static.m_NumPrevBits == numPrevBits &&
    this$static.m_NumPosBits == numPosBits
  ) {
    return
  }
  this$static.m_NumPosBits = numPosBits
  this$static.m_PosMask = (1 << numPosBits) - 1
  this$static.m_NumPrevBits = numPrevBits
  numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  this$static.m_Coders = initDim(numStates)
  for (i = 0; i < numStates; ++i) {
    this$static.m_Coders[i] = $Encoder$LiteralEncoder$Encoder2({})
  }
}

function $GetSubCoder(this$static, pos, prevByte) {
  return this$static.m_Coders[
    ((pos & this$static.m_PosMask) << this$static.m_NumPrevBits) +
      ((prevByte & 255) >>> (8 - this$static.m_NumPrevBits))
  ]
}

function $Init_3(this$static) {
  var i,
    numStates = 1 << (this$static.m_NumPrevBits + this$static.m_NumPosBits)
  for (i = 0; i < numStates; ++i) {
    InitBitModels(this$static.m_Coders[i].m_Encoders)
  }
}

function $Encode_1(this$static, rangeEncoder, symbol) {
  var bit,
    i,
    context = 1
  for (i = 7; i >= 0; --i) {
    bit = (symbol >> i) & 1
    $Encode_3(rangeEncoder, this$static.m_Encoders, context, bit)
    context = (context << 1) | bit
  }
}

function $EncodeMatched(this$static, rangeEncoder, matchByte, symbol) {
  var bit,
    i,
    matchBit,
    state,
    same = 1,
    context = 1
  for (i = 7; i >= 0; --i) {
    bit = (symbol >> i) & 1
    state = context
    if (same) {
      matchBit = (matchByte >> i) & 1
      state += (1 + matchBit) << 8
      same = matchBit == bit
    }
    $Encode_3(rangeEncoder, this$static.m_Encoders, state, bit)
    context = (context << 1) | bit
  }
}

function $Encoder$LiteralEncoder$Encoder2(this$static) {
  this$static.m_Encoders = initDim(768)
  return this$static
}

function $GetPrice_0(this$static, matchMode, matchByte, symbol) {
  var bit,
    context = 1,
    i = 7,
    matchBit,
    price = 0
  if (matchMode) {
    for (; i >= 0; --i) {
      matchBit = (matchByte >> i) & 1
      bit = (symbol >> i) & 1
      price += GetPrice(
        this$static.m_Encoders[((1 + matchBit) << 8) + context],
        bit
      )
      context = (context << 1) | bit
      if (matchBit != bit) {
        --i
        break
      }
    }
  }
  for (; i >= 0; --i) {
    bit = (symbol >> i) & 1
    price += GetPrice(this$static.m_Encoders[context], bit)
    context = (context << 1) | bit
  }
  return price
}

function $MakeAsChar(this$static) {
  this$static.BackPrev = -1
  this$static.Prev1IsChar = 0
}

function $MakeAsShortRep(this$static) {
  this$static.BackPrev = 0
  this$static.Prev1IsChar = 0
}
function $BitTreeDecoder(this$static, numBitLevels) {
  this$static.NumBitLevels = numBitLevels
  this$static.Models = initDim(1 << numBitLevels)
  return this$static
}

function $Decode_0(this$static, rangeDecoder) {
  var bitIndex,
    m = 1
  for (bitIndex = this$static.NumBitLevels; bitIndex != 0; --bitIndex) {
    m = (m << 1) + $DecodeBit(rangeDecoder, this$static.Models, m)
  }
  return m - (1 << this$static.NumBitLevels)
}

function $ReverseDecode(this$static, rangeDecoder) {
  var bit,
    bitIndex,
    m = 1,
    symbol = 0
  for (bitIndex = 0; bitIndex < this$static.NumBitLevels; ++bitIndex) {
    bit = $DecodeBit(rangeDecoder, this$static.Models, m)
    m <<= 1
    m += bit
    symbol |= bit << bitIndex
  }
  return symbol
}

function ReverseDecode(Models, startIndex, rangeDecoder, NumBitLevels) {
  var bit,
    bitIndex,
    m = 1,
    symbol = 0
  for (bitIndex = 0; bitIndex < NumBitLevels; ++bitIndex) {
    bit = $DecodeBit(rangeDecoder, Models, startIndex + m)
    m <<= 1
    m += bit
    symbol |= bit << bitIndex
  }
  return symbol
}
function $BitTreeEncoder(this$static, numBitLevels) {
  this$static.NumBitLevels = numBitLevels
  this$static.Models = initDim(1 << numBitLevels)
  return this$static
}

function $Encode_2(this$static, rangeEncoder, symbol) {
  var bit,
    bitIndex,
    m = 1
  for (bitIndex = this$static.NumBitLevels; bitIndex != 0; ) {
    --bitIndex
    bit = (symbol >>> bitIndex) & 1
    $Encode_3(rangeEncoder, this$static.Models, m, bit)
    m = (m << 1) | bit
  }
}

function $GetPrice_1(this$static, symbol) {
  var bit,
    bitIndex,
    m = 1,
    price = 0
  for (bitIndex = this$static.NumBitLevels; bitIndex != 0; ) {
    --bitIndex
    bit = (symbol >>> bitIndex) & 1
    price += GetPrice(this$static.Models[m], bit)
    m = (m << 1) + bit
  }
  return price
}

function $ReverseEncode(this$static, rangeEncoder, symbol) {
  var bit,
    i,
    m = 1
  for (i = 0; i < this$static.NumBitLevels; ++i) {
    bit = symbol & 1
    $Encode_3(rangeEncoder, this$static.Models, m, bit)
    m = (m << 1) | bit
    symbol >>= 1
  }
}

function $ReverseGetPrice(this$static, symbol) {
  var bit,
    i,
    m = 1,
    price = 0
  for (i = this$static.NumBitLevels; i != 0; --i) {
    bit = symbol & 1
    symbol >>>= 1
    price += GetPrice(this$static.Models[m], bit)
    m = (m << 1) | bit
  }
  return price
}

function ReverseEncode(Models, startIndex, rangeEncoder, NumBitLevels, symbol) {
  var bit,
    i,
    m = 1
  for (i = 0; i < NumBitLevels; ++i) {
    bit = symbol & 1
    $Encode_3(rangeEncoder, Models, startIndex + m, bit)
    m = (m << 1) | bit
    symbol >>= 1
  }
}

function ReverseGetPrice(Models, startIndex, NumBitLevels, symbol) {
  var bit,
    i,
    m = 1,
    price = 0
  for (i = NumBitLevels; i != 0; --i) {
    bit = symbol & 1
    symbol >>>= 1
    price += ProbPrices[(((Models[startIndex + m] - bit) ^ -bit) & 2047) >>> 2]
    m = (m << 1) | bit
  }
  return price
}
function $DecodeBit(this$static, probs, index) {
  var newBound,
    prob = probs[index]
  newBound = (this$static.Range >>> 11) * prob
  if ((this$static.Code ^ -2147483648) < (newBound ^ -2147483648)) {
    this$static.Range = newBound
    probs[index] = ((prob + ((2048 - prob) >>> 5)) << 16) >> 16
    if (!(this$static.Range & -16777216)) {
      this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
      this$static.Range <<= 8
    }
    return 0
  } else {
    this$static.Range -= newBound
    this$static.Code -= newBound
    probs[index] = ((prob - (prob >>> 5)) << 16) >> 16
    if (!(this$static.Range & -16777216)) {
      this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
      this$static.Range <<= 8
    }
    return 1
  }
}

function $DecodeDirectBits(this$static, numTotalBits) {
  var i,
    t,
    result = 0
  for (i = numTotalBits; i != 0; --i) {
    this$static.Range >>>= 1
    t = (this$static.Code - this$static.Range) >>> 31
    this$static.Code -= this$static.Range & (t - 1)
    result = (result << 1) | (1 - t)
    if (!(this$static.Range & -16777216)) {
      this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
      this$static.Range <<= 8
    }
  }
  return result
}

function $Init_8(this$static) {
  this$static.Code = 0
  this$static.Range = -1
  for (var i = 0; i < 5; ++i) {
    this$static.Code = (this$static.Code << 8) | $read(this$static.Stream)
  }
}
function InitBitModels(probs) {
  for (var i = probs.length - 1; i >= 0; --i) {
    probs[i] = 1024
  }
}
var ProbPrices = (function() {
  var end,
    i,
    j,
    start,
    ProbPrices = []
  for (i = 8; i >= 0; --i) {
    start = 1 << (9 - i - 1)
    end = 1 << (9 - i)
    for (j = start; j < end; ++j) {
      ProbPrices[j] = (i << 6) + (((end - j) << 6) >>> (9 - i - 1))
    }
  }
  return ProbPrices
})()

function $Encode_3(this$static, probs, index, symbol) {
  var newBound,
    prob = probs[index]
  newBound = (this$static.Range >>> 11) * prob
  if (!symbol) {
    this$static.Range = newBound
    probs[index] = ((prob + ((2048 - prob) >>> 5)) << 16) >> 16
  } else {
    this$static.Low = add(
      this$static.Low,
      and(fromInt(newBound), [4294967295, 0])
    )
    this$static.Range -= newBound
    probs[index] = ((prob - (prob >>> 5)) << 16) >> 16
  }
  if (!(this$static.Range & -16777216)) {
    this$static.Range <<= 8
    $ShiftLow(this$static)
  }
}

function $EncodeDirectBits(this$static, v, numTotalBits) {
  for (var i = numTotalBits - 1; i >= 0; --i) {
    this$static.Range >>>= 1
    if (((v >>> i) & 1) == 1) {
      this$static.Low = add(this$static.Low, fromInt(this$static.Range))
    }
    if (!(this$static.Range & -16777216)) {
      this$static.Range <<= 8
      $ShiftLow(this$static)
    }
  }
}

function $GetProcessedSizeAdd(this$static) {
  return add(add(fromInt(this$static._cacheSize), this$static._position), [
    4,
    0
  ])
}

function $Init_9(this$static) {
  this$static._position = P0_longLit
  this$static.Low = P0_longLit
  this$static.Range = -1
  this$static._cacheSize = 1
  this$static._cache = 0
}

function $ShiftLow(this$static) {
  var temp,
    LowHi = lowBits_0(shru(this$static.Low, 32))
  if (LowHi != 0 || compare(this$static.Low, [4278190080, 0]) < 0) {
    this$static._position = add(
      this$static._position,
      fromInt(this$static._cacheSize)
    )
    temp = this$static._cache
    do {
      $write(this$static.Stream, temp + LowHi)
      temp = 255
    } while (--this$static._cacheSize != 0)
    this$static._cache = lowBits_0(this$static.Low) >>> 24
  }
  ++this$static._cacheSize
  this$static.Low = shl(and(this$static.Low, [16777215, 0]), 8)
}

function GetPrice(Prob, symbol) {
  return ProbPrices[(((Prob - symbol) ^ -symbol) & 2047) >>> 2]
}
function decode(utf) {
  var i = 0,
    j = 0,
    x,
    y,
    z,
    l = utf.length,
    buf = [],
    charCodes = []
  for (; i < l; ++i, ++j) {
    x = utf[i] & 255
    if (!(x & 128)) {
      if (!x) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      charCodes[j] = x
    } else if ((x & 224) == 192) {
      if (i + 1 >= l) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      y = utf[++i] & 255
      if ((y & 192) != 128) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      charCodes[j] = ((x & 31) << 6) | (y & 63)
    } else if ((x & 240) == 224) {
      if (i + 2 >= l) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      y = utf[++i] & 255
      if ((y & 192) != 128) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      z = utf[++i] & 255
      if ((z & 192) != 128) {
        // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
        return utf
      }
      charCodes[j] = ((x & 15) << 12) | ((y & 63) << 6) | (z & 63)
    } else {
      // It appears that this is binary data, so it cannot be converted to a string, so just send it back.
      return utf
    }
    if (j == 16383) {
      buf.push(String.fromCharCode.apply(String, charCodes))
      j = -1
    }
  }
  if (j > 0) {
    charCodes.length = j
    buf.push(String.fromCharCode.apply(String, charCodes))
  }
  return buf.join('')
}
function encode(s) {
  var ch,
    chars = [],
    data,
    elen = 0,
    i,
    l = s.length
  // Be able to handle binary arrays and buffers.
  if (typeof s == 'object') {
    return s
  } else {
    $getChars(s, 0, l, chars, 0)
  }
  // Add extra spaces in the array to break up the unicode symbols.
  for (i = 0; i < l; ++i) {
    ch = chars[i]
    if (ch >= 1 && ch <= 127) {
      ++elen
    } else if (!ch || (ch >= 128 && ch <= 2047)) {
      elen += 2
    } else {
      elen += 3
    }
  }
  data = []
  elen = 0
  for (i = 0; i < l; ++i) {
    ch = chars[i]
    if (ch >= 1 && ch <= 127) {
      data[elen++] = (ch << 24) >> 24
    } else if (!ch || (ch >= 128 && ch <= 2047)) {
      data[elen++] = ((192 | ((ch >> 6) & 31)) << 24) >> 24
      data[elen++] = ((128 | (ch & 63)) << 24) >> 24
    } else {
      data[elen++] = ((224 | ((ch >> 12) & 15)) << 24) >> 24
      data[elen++] = ((128 | ((ch >> 6) & 63)) << 24) >> 24
      data[elen++] = ((128 | (ch & 63)) << 24) >> 24
    }
  }
  return data
}
// s is dictionarySize
// f is fb
// m is matchFinder
// NOTE: Because some values are always the same, they have been removed.
// lc is always 3
// lp is always 0
// pb is always 2
const modes = [
  { s: 16, f: 64, m: 0 },
  { s: 20, f: 64, m: 0 },
  { s: 19, f: 64, m: 1 },
  { s: 20, f: 64, m: 1 },
  { s: 21, f: 128, m: 1 },
  { s: 22, f: 128, m: 1 },
  { s: 23, f: 128, m: 1 },
  { s: 24, f: 255, m: 1 },
  { s: 25, f: 255, m: 1 }
]

function get_mode_obj(mode) {
  return modes[mode - 1] || modes[6]
}

/**
 * Compress a string with the LZMA algorithm
 *
 * @param {string}            value                 The string to be compressed
 * @param {object}            options
 * @param {1|2|3|4|5|6|7|8|9} options.mode          Which mode to use (1 through 9, defaults to 7)
 * @param {boolean}           options.enableEndMark Whether to write an end mark
 * @returns {string}
 */
export function compress(value, { mode = 7, enableEndMark = true } = {}) {
  var this$static = {}

  this$static.c = $LZMAByteArrayCompressor(
    {},
    encode(value),
    get_mode_obj(mode),
    enableEndMark
  )
  while ($processChunk(this$static.c.chunker));
  return $toByteArray(this$static.c.output)
}

/**
 * Compress a string with the LZMA algorithm to URL-safe characters
 *
 * @param {string}            value                 The string to be compressed
 * @param {object}            options
 * @param {1|2|3|4|5|6|7|8|9} options.mode          Which mode to use (1 through 9, defaults to 7)
 * @param {boolean}           options.enableEndMark Whether to write an end mark
 * @returns {string}
 */
export function compressUrlSafe(
  string,
  { mode = 7, enableEndMark = true } = {}
) {
  const compressedString = compress(string, { mode, enableEndMark })
  const compressedBytes = new Uint8Array(compressedString)

  return base64.encodeFromArrayUrlSafe(compressedBytes)
}

/**
 * Decompress a string compressed with the LZMA algorithm
 *
 * @param {number[]|Int8Array} bytes The int8 array created by the compress() function
 * @returns {string}
 */
export function decompress(bytes) {
  var this$static = {}

  this$static.d = $LZMAByteArrayDecompressor({}, bytes)
  while ($processChunk(this$static.d.chunker));
  return decode($toByteArray(this$static.d.output))
}

/**
 * Decompress a string compressed with the URL-safe compress function
 *
 * @param {string} string The URL-safe string generated by the compressUrlSafe() function
 * @returns {string}
 */
export function decompressUrlSafe(string) {
  return decompress(new Int8Array(base64.decodeToArrayUrlSafe(string)))
}
